// 创建axios实例
import axios from 'axios'
import store from '@/store'
import router from '@/router'
import http from '@/utils/request'
// 导入处理大数字的包 JSONbig这个包也有两个方法
// JSONbig.stringify() JSONbig.parse()
import JSONbig from 'json-bigint'
import { reqGetNewToken } from '@/api/user'
const instance = axios.create({
  // 基地址
  baseURL: 'http://toutiao-app.itheima.net/',
  // 服务器超过5s之后没有响应,我就不要了
  timeout: 5000,
  // 手动处理响应的数据， 如果这个节点不配置，默认axios帮我们处理, 如果配置了,以我们自己配置的为准
  transformResponse: [function (data) {
    // data就是响应的数据 只不过是字符串格式的
    // json-bigint 这个包是专门处理大数字的包
    // 后台有可能响应的数据不是json格式的字符串, 转换就会报错, 当前项目中没有这个问题
    try {
      return JSONbig.parse(data)
    } catch (error) {
      return data
    }
  }]
})
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
  // 在发送请求前做一些事情
  // config 当前发送的请求的配置信息 参数 请求方式 地址 ... headers 可以在这个headers中携带token
  // console.log(config.headers.a = 10)
  // console.log(config)
  const token = store.state.user.tokenInfo.token
  // 如果有token 再挂载
  if (token && !config.headers.Authorization) {
    // console.log('重新挂载了一次')
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
}, function (error) {
  // Do something with request error
  return Promise.reject(error)
})
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  // console.log(response) // axios包装后响应的数据,中有data才是浏览器需要的数据
  // console.log(response.data)
  return response.data
}, async function (error) {
  // 对响应错误做点什么 ---error 响应失败的错误对象
  // console.log('响应失败了')
  console.dir(error)
  // 1.刷新token的操作了, 如果错误状态码是401, 说明token过期了,我们要进行刷新token
  if (error.response.status === 401) {
    const refresh_token = store.state.user.tokenInfo.refresh_token
    // 4. 如果有refresh_token 刷新得到新的token
    if (refresh_token) {
      try {
        // console.log('刷新新的token')
        const { data: { token } } = await reqGetNewToken(refresh_token)
        console.log(token) // 新的token
        // 5.将新token存储在veux和本地存储 直接提交mutation即可
        store.commit('user/setTokenInfo', {
          token,
          refresh_token
        })
        // 6. 重新发送上一次失败的请求, 并且要携带上最新的token
        // error错误对象中有一个config 也是一个对象, 就是上次请求失败的请求的配置信息
        // console.log(error.config)
        // error.config 他的headers中的Authorization字段还是请求失败那次带的过期的token, 更新成最新的
        error.config.headers.Authorization = `Bearer ${token}` // 必须写, 卡死
        return http(error.config)
      } catch {
        // 7 refresh_token也过期的情况
        router.push({
          path: '/login',
          query: {
            backTo: router.currentRoute.fullPath
          }
        })
        // 提交清除tokenInfo的mutation
        store.commit('user/removeTokenInfo')
      }
    } else {
      // 2.没有refresh_token, 路由只能重新登录
      // router.currentRoute === this.$route 表示当前路由地址信息对象
      router.push({
        path: '/login',
        query: {
          backTo: router.currentRoute.fullPath
        }
      })
      // 3.为了让代码更健壮, 清除无用的存储 tokenInfo vuex中和本地存储都要清除
      // 提交清除tokenInfo的mutation
      store.commit('user/removeTokenInfo')
    }
  }

  return Promise.reject(error)
})
export default instance
